#include "HaffmanEncoder.h"
#include<io.h>
#include "UnitTest.h"

void HaffmanEncoder::encode(ICodeTable* table, IDataReader* reader, IDataWriter* writer)
{
  char buff = 0;
     int count = 0;
     while(!reader->isNextEnd())
     {
		char c = reader->getChar();
		vector<bool> x = table->getCode(c);
		for(size_t j = 0; j < x.size();++j)
        {
			buff = buff | x[j]<<(7-count);
			++count;
			if(count==8)
			{
				count = 0;
				writer->putChar(buff);
				buff = 0;
			}
		}
	 }
	 if(count != 0)
		 writer->putChar(buff);
}

void HaffmanEncoder::engine(IDataReader* reader, IDataWriter* writer, IFrequencyBuilder* frequencyBuilder, ITreeFactory* treeFactory, ICodeTableFactory* tableFactory,ITreeWriter*  treeWriter)
{
	frequencyBuilder->build(reader);
	IFrequencyTable* frTable = frequencyBuilder->getFrequencyTable();
	INode* tree = treeFactory->create(frTable);
	treeWriter->write(tree,writer);
          
    encode(tableFactory->create(tree),reader,writer);
}

void HaffmanEncoder::start(char* input, char* output)
{
	if(access(input,0) != -1)
		engine(&TextReader(input),&TextWriter(output),&FrequencyBuilder(),&TreeFactory(),&CodeTableFactory(),&TreeWriter());		
	else
		throw;
}